package com.snail.file;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.*;

/**
 * 磁盘速度是固定的，写入数据设计到锁的竞争，所以在这里单线程比多线程写入快。
 * 但是通过增加一层缓存，肯定比直接写文件速度快。
 * @author WuQinglong created on 2021/12/27 17:11
 */
public class MainTest {

    public static void main(String[] args) {
        // 日志数据
        String msg = "2021-12-27 16:50:00,035 [INFO ] RID= -- [Thread-861] com.snail.UserService" +
                ".[xxxx][203]: 【日志日志日志日志】日志：{\"id\":1111,\"orderNo\":\"xxxxx\",\"term\":12," +
                "\"amount\":0.1000}";

        singleThread(msg);
//        mulitThread(msg, 4);
    }

    /**
     * 单线程写入
     */
    private static void singleThread(String msg) {
        int msgLength = msg.getBytes(StandardCharsets.UTF_8).length;

        // 写入多少秒的数据
        int runSecond = 10;
        new Thread(() -> {
            long startTs = System.currentTimeMillis();
            long stopTs = startTs + runSecond * 1000;
            long writeLength = 0;
            while (true) {
                // 使用缓存进行写文件
                LogHelper.log(msg);

                // 对比写完立马刷盘，与写完不刷盘的性能
//                LogHelper.flush();

                if (System.currentTimeMillis() > stopTs) {
                    // 计算每秒写入量 KB/s MB/s
                    long rate = (writeLength / 1024) / runSecond;
                    System.out.println("磁盘写入速率为：" + (rate / 1024.0) + "MB/s");
                    break;
                }

                writeLength += msgLength;
            }
        }).start();
        LogHelper.flushThreadRunning = false;
    }

    /**
     * 多线程写入
     */
    private static void mulitThread(String msg, int threadCount) {
        int msgLength = msg.getBytes(StandardCharsets.UTF_8).length;

        // 写入多少秒的数据
        int runSecond = 5;

        ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCount, threadCount,
                60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(threadCount));
        executor.prestartAllCoreThreads();

        for (int i = 0; i < threadCount; i++) {
            executor.submit(() -> {
                long startTs = System.currentTimeMillis();
                long stopTs = startTs + runSecond * 1000;
                long writeLength = 0;
                while (true) {
                    // 使用缓存进行写文件
                    LogHelper.log(msg);

                    // 对比写完立马刷盘，与写完不刷盘的性能
//                    LogHelper.flush();

                    if (System.currentTimeMillis() > stopTs) {
                        // 计算每秒写入量 KB/s MB/s
                        long rate = (writeLength / 1024) / runSecond;
                        System.out.println(Thread.currentThread().getName() + ": 磁盘写入速率为：" + (rate / 1024.0) + "MB/s");
                        break;
                    }

                    writeLength += msgLength;
                }
            });
        }

        while (executor.getActiveCount() > 0) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                // ignore
            }
        }
        LogHelper.flushThreadRunning = false;
        executor.shutdown();
    }

}
